﻿using UnityEngine;
using UnityEngine.Rendering;
using UnityEngine.Rendering.Universal;

public class BlurRenderPassFeature : ScriptableRendererFeature
{

    [Space]
    public RenderPassEvent renderPassEvent = RenderPassEvent.AfterRenderingOpaques;
    public Material blurMaterial;
    [Range(1, 4)] public int downsample = 1;
    [Range(0, 20)] public int blurStrength = 5;

    CustomRenderPass m_ScriptablePass;

    public override void Create()
    {
        m_ScriptablePass = new CustomRenderPass(this);

        // Configures where the render pass should be injected.
        m_ScriptablePass.renderPassEvent = renderPassEvent;
    }

    // Here you can inject one or multiple render passes in the renderer.
    // This method is called when setting up the renderer once per-camera.
    public override void AddRenderPasses(ScriptableRenderer renderer, ref RenderingData renderingData)
    {
        m_ScriptablePass.Setup(renderer.cameraColorTarget, renderingData.cameraData);
        renderer.EnqueuePass(m_ScriptablePass);
    }





    //=========================================
    //=========================================
    //=========================================
    class CustomRenderPass : ScriptableRenderPass
    {
        private BlurRenderPassFeature _renderPassFeature;

        const string ProfilerTag = "Blur Pass";

        RenderTargetIdentifier colorBuffer, temporaryBuffer;
        int temporaryBufferID = Shader.PropertyToID("_TemporaryBuffer");
        int blurStrengthID = Shader.PropertyToID("_BlurStrength");

        public CustomRenderPass(BlurRenderPassFeature renderPassFeature)
        {
            _renderPassFeature = renderPassFeature;
            temporaryBuffer = new RenderTargetIdentifier(temporaryBufferID);
        }

        public void Setup(RenderTargetIdentifier cameraColorBuffer, CameraData cameraData)
        {
            colorBuffer = cameraColorBuffer;
        }

        // This method is called before executing the render pass.
        // It can be used to configure render targets and their clear state. Also to create temporary render target textures.
        // When empty this render pass will render to the active camera render target.
        // You should never call CommandBuffer.SetRenderTarget. Instead call <c>ConfigureTarget</c> and <c>ConfigureClear</c>.
        // The render pipeline will ensure target setup and clearing happens in an performance manner.
        public override void Configure(CommandBuffer cmd, RenderTextureDescriptor cameraTextureDescriptor)
        {
            _renderPassFeature.blurMaterial.SetInt(blurStrengthID, _renderPassFeature.blurStrength);
            cameraTextureDescriptor.depthBufferBits = 0;
            cameraTextureDescriptor.width /= _renderPassFeature.downsample;
            cameraTextureDescriptor.height /= _renderPassFeature.downsample;

            cmd.GetTemporaryRT(temporaryBufferID, cameraTextureDescriptor, FilterMode.Bilinear);
        }

        // Here you can implement the rendering logic.
        // Use <c>ScriptableRenderContext</c> to issue drawing commands or execute command buffers
        // https://docs.unity3d.com/ScriptReference/Rendering.ScriptableRenderContext.html
        // You don't have to call ScriptableRenderContext.submit, the render pipeline will call it at specific points in the pipeline.
        public override void Execute(ScriptableRenderContext context, ref RenderingData renderingData)
        {
            CommandBuffer cmd = CommandBufferPool.Get();
            using (new ProfilingScope(cmd, new ProfilingSampler(ProfilerTag)))
            {
                // Blit from the color buffer to a temporary buffer and back. This is needed for a two-pass shader.
                Blit(cmd, colorBuffer, temporaryBuffer, _renderPassFeature.blurMaterial, 0); // shader pass 0
                Blit(cmd, temporaryBuffer, colorBuffer, _renderPassFeature.blurMaterial, 1); // shader pass 1
            }

            context.ExecuteCommandBuffer(cmd);
            CommandBufferPool.Release(cmd);
        }

        /// Cleanup any allocated resources that were created during the execution of this render pass.
        public override void FrameCleanup(CommandBuffer cmd)
        {
            cmd.ReleaseTemporaryRT(temporaryBufferID);
        }
    }











}


